#include "rtpreceiver.h"
#include <QDebug>

#include <QCoreApplication>
#include <QDir>

#include <QDateTime>
#include <QMutex>

QMutex fileMutex;  // 全局互斥量声明

RtpReceiver::RtpReceiver(quint16 receivePort,  QString strSDP_SPS)
    : m_receivePort(receivePort)
    ,m_SDP_SPS(strSDP_SPS)
{

}

void RtpReceiver::run()
{
    QUdpSocket socket;
    if (!socket.bind(QHostAddress("127.0.0.1"), m_receivePort))
    {
        qWarning() << "Bind failed";
        return;
    }

    //保存在exe所在路径下，新建文件
    // QString timeStr1 = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
    // qDebug() << "Method 1:" << timeStr1;

    // QString exeDir = QCoreApplication::applicationDirPath();
    // QString filePath = exeDir + "/" + timeStr1 + ".264";

    // QFile file(filePath);
    // if (!file.open(QIODevice::WriteOnly)) //会自动创建
    // {
    //     qWarning() << "File open failed";
    //     return;
    // }

    // Write start code and SPS/PPS if available
    //在接收的RTP数据中，第一个数据包，将SPS PPS SEI 打成了一个包，所以需要对这种情况进行兼容
    //80 60 03 1e a6 9c c3 ba 4d b5 c3 78 18 00 17   //15字节的RTP头
    //67 64 00 0b ac d9 42 04 68 40 00 00 03 00 40 00 00 0f 03 c5 0a 65 80 00 06  //SPS
    //68 eb e3 cb 22 c0 02 ae //PPS
    // 06 05 ff ff aa ...  //SEI

    //直接从SDP信息中获取到SPS/PPS
    //sprop-parameter-sets=Z2QAC6zZQgRoQAAAAwBAAAAPA8UKZYA=,aOvjyyLA;

    QStringList params = m_SDP_SPS.split(',');
    QString strSPS = params[0];
    QString strPPS = params[1];

    QByteArray spsData = QByteArray::fromBase64(strSPS.toLatin1());
    QByteArray ppsData = QByteArray::fromBase64(strPPS.toLatin1());

    {
        //QMutexLocker locker(&fileMutex);
        emit writefile(spsData);
        emit writefile(ppsData);
        // file.write("\x00\x00\x00\x01", 4);
        // file.write(spsData);
        // file.write("\x00\x00\x00\x01", 4);
        // file.write(ppsData);
    }


    QByteArray datagram;
    uint8_t payloadType;
    bool marker;
    uint16_t seq;

    uint8_t *payload = nullptr;
    uint8_t nalType;

    while (!isInterruptionRequested())
    {
        if (socket.hasPendingDatagrams())
        {
            datagram.clear();
            datagram.resize(socket.pendingDatagramSize());
            socket.readDatagram(datagram.data(), datagram.size()); //将UDP数据包内容读入缓冲区

            //qInfo() << datagram.toHex(' ');

            // RTP header parsing (12 bytes)
            if (datagram.size() < 12)
            {
                qInfo() << "error";
                continue;   //RTP头部验证
            }

            //RTP头部解析
            payloadType = datagram[1] & 0x7F;  //提取7位有效负载类型（0-127）
            marker = datagram[1] & 0x80;  //检测最高位标记位（帧结束标志）
            seq = (datagram[2] << 8) | datagram[3];  //组合16位序列号（大端序）


            // H264 payload processing
            payload = (uint8_t*)datagram.data() + 12;  //定位RTP负载起始位置（跳过12字节头部）
            nalType = payload[0] & 0x1F;  //提取NALU类型（5位有效值，0-31）

            if (nalType == 28)
            { // FU-A  分片
                uint8_t startBit = payload[1] & 0x80;
                uint8_t endBit = payload[1] & 0x40;
                uint8_t nalType = payload[1] & 0x1F;

                if (startBit)
                {
                    m_currentNalu.clear();
                    m_currentNalu.append((payload[0] & 0xE0) | nalType);
                }
                m_currentNalu.append(reinterpret_cast<const char*>(payload + 2), datagram.size() - 14);  //缓存分片数据，接收完成后再写入文件

                if (endBit)
                {
                    //QMutexLocker locker(&fileMutex);
                    emit writefile(m_currentNalu);
                    // file.write("\x00\x00\x00\x01", 4);
                    // file.write(m_currentNalu);
                }
            }
            else if (nalType != 1 &&
                    nalType != 2 &&
                    nalType != 5 &&
                    nalType != 7 &&
                    nalType != 8 &&
                    nalType != 9)
            {
                //未知类型
                continue;
            }
            else
            { // Single NALU  直接写入文件
                QByteArray bytearrNalu;
                bytearrNalu.append(reinterpret_cast<const char*>(payload), datagram.size() - 12);

               // QMutexLocker locker(&fileMutex);
                //file.write("\x00\x00\x00\x01", 4);
                //file.write(bytearrNalu);
                emit writefile(bytearrNalu);

                //file.flush();  // 强制刷新
            }
        }
    }
   // file.close();
}
